import { Injectable } from '@nestjs/common';
import { Yao, GuaXiang, BianGua, DivinationRequest, DivinationResponse } from './yijing.types';
import { SIXTY_FOUR_GUAS, YAO_CI } from './yijing.constants';
import { DeepSeekService } from '../deepseek/deepseek.service';

@Injectable()
export class YijingService {
  constructor(private readonly deepSeekService: DeepSeekService) {}
  /**
   * 生成卦象
   * @param numbers 三个数字
   * @param question 用户问题（可选）
   */
  async generateGuaXiang(numbers: number[], question?: string): Promise<DivinationResponse> {
    // 验证输入
    if (numbers.length !== 3) {
      throw new Error('需要三个数字');
    }
    // 计算六爻
    const yaos = this.calculateYaos(numbers);
    
    // 获取卦象信息
    const guaXiang = this.getGuaXiangInfo(yaos);
    
    // 检查是否有变爻
    const changingYaos = yaos
      .map((yao, index) => (yao.isChanging ? index : -1))
      .filter(index => index !== -1);

    let bianGua: BianGua | undefined;
    if (changingYaos.length > 0) {
      bianGua = this.generateBianGua(yaos, changingYaos);
    }

    // 生成解读（传递用户问题）
    const interpretation = await this.generateInterpretation(guaXiang, bianGua, question);

    return {
      guaXiang,
      bianGua,
      interpretation
    };
  }

  /**
   * 计算六爻
   */
  private calculateYaos(numbers: number[]): Yao[] {
    const yaos: Yao[] = [];
    
    // 第一个数字除以4的余数决定初爻
    const remainder1 = numbers[0] % 4;
    yaos.push(this.getYaoValue(remainder1));

    // 第二个数字除以4的余数决定二爻
    const remainder2 = numbers[1] % 4;
    yaos.push(this.getYaoValue(remainder2));

    // 第三个数字除以4的余数决定三爻
    const remainder3 = numbers[2] % 4;
    yaos.push(this.getYaoValue(remainder3));

    // 用同样的方法计算上三爻（重复使用三个数字）
    const remainder4 = numbers[0] % 4;
    yaos.push(this.getYaoValue(remainder4));

    const remainder5 = numbers[1] % 4;
    yaos.push(this.getYaoValue(remainder5));

    const remainder6 = numbers[2] % 4;
    yaos.push(this.getYaoValue(remainder6));

    return yaos;
  }

  /**
   * 根据余数获取爻的值
   */
  private getYaoValue(remainder: number): Yao {
    // 余数对应关系：
    // 0 -> 6 (老阴，变爻)
    // 1 -> 7 (少阳)
    // 2 -> 8 (少阴) 
    // 3 -> 9 (老阳，变爻)
    const valueMap = [6, 7, 8, 9];
    const yaoValue = valueMap[remainder];
    
    return {
      value: yaoValue,
      isChanging: yaoValue === 6 || yaoValue === 9
    };
  }

  /**
   * 获取卦象信息
   */
  private getGuaXiangInfo(yaos: Yao[]): GuaXiang {
    // 将爻转换为二进制表示（阳爻为1，阴爻为0），从下到上的顺序
    const binary = yaos.reduce((acc, yao, index) => {
      const bit = yao.value === 7 || yao.value === 9 ? 1 : 0;
      // 从下到上：初爻(index=0)对应最低位，上爻(index=5)对应最高位
      return acc | (bit << index);
    }, 0);

    // 查找对应的卦
    const gua = SIXTY_FOUR_GUAS.find(g => g.binary === binary);
    
    if (!gua) {
      // 如果找不到对应的卦，返回一个默认的卦象信息
      return {
        yaos,
        guaName: '未知',
        guaCi: '此卦象暂无详细解读',
        xiangCi: '请尝试其他数字组合'
      };
    }

    return {
      yaos,
      guaName: gua.name,
      guaCi: gua.guaCi,
      xiangCi: gua.xiangCi
    };
  }

  /**
   * 生成变卦
   */
  private generateBianGua(originalYaos: Yao[], changingYaos: number[]): BianGua {
    // 复制原始爻
    const changedYaos = [...originalYaos];
    
    // 变爻：老阴变阳，老阳变阴
    changingYaos.forEach(index => {
      const yao = changedYaos[index];
      if (yao.value === 6) { // 老阴变阳
        changedYaos[index] = { value: 7, isChanging: false };
      } else if (yao.value === 9) { // 老阳变阴
        changedYaos[index] = { value: 8, isChanging: false };
      }
    });

    const changedGuaXiang = this.getGuaXiangInfo(changedYaos);

    return {
      original: this.getGuaXiangInfo(originalYaos),
      changed: changedGuaXiang,
      changingYaos
    };
  }

  /**
   * 生成解读
   */
  private async generateInterpretation(guaXiang: GuaXiang, bianGua?: BianGua, question?: string): Promise<string> {
    try {
      // 使用DeepSeek AI进行解卦
      const aiInterpretation = await this.deepSeekService.interpretGua({
        guaName: guaXiang.guaName,
        guaCi: guaXiang.guaCi,
        xiangCi: guaXiang.xiangCi,
        changingYao: bianGua?.changingYaos,
        userQuestion: question
      });
      let interpretation = `您得到了${guaXiang.guaName}卦。\n\n`;
      interpretation += `卦辞：${guaXiang.guaCi}\n`;
      interpretation += `象辞：${guaXiang.xiangCi}\n\n`;

      if (bianGua) {
        interpretation += `本卦中有${bianGua.changingYaos.length}个变爻，变卦为${bianGua.changed.guaName}卦。\n`;
        interpretation += `变卦卦辞：${bianGua.changed.guaCi}\n\n`;
      }

      interpretation += `AI解读：${aiInterpretation.interpretation}\n\n`;
      
      if (aiInterpretation.advice) {
        interpretation += `建议：${aiInterpretation.advice}\n`;
      }

      return interpretation;
    } catch (error) {
      console.error('AI解卦失败，使用默认解读:', error);
      
      // AI服务不可用时使用默认解读
      let interpretation = `您得到了${guaXiang.guaName}卦。\n\n`;
      interpretation += `卦辞：${guaXiang.guaCi}\n`;
      interpretation += `象辞：${guaXiang.xiangCi}\n\n`;

      if (bianGua) {
        interpretation += `本卦中有${bianGua.changingYaos.length}个变爻，变卦为${bianGua.changed.guaName}卦。\n`;
        interpretation += `变卦卦辞：${bianGua.changed.guaCi}\n`;
      }

      interpretation += '此卦象征天地交泰，阴阳和谐，预示着良好的发展和机遇。';

      return interpretation;
    }
  }

  /**
   * 生成随机数字卦
   */
  async generateRandomGua(question?: string): Promise<DivinationResponse> {
    const numbers = [
      Math.floor(Math.random() * 100) + 1,
      Math.floor(Math.random() * 100) + 1,
      Math.floor(Math.random() * 100) + 1
    ];
    
    return this.generateGuaXiang(numbers, question);
  }

  /**
   * 硬币算卦法
   * 三枚硬币抛六次，每次结果：
   * - 3个正面（3阳）：老阳（9，变爻）
   * - 2个正面（2阳1阴）：少阳（7）
   * - 1个正面（1阳2阴）：少阴（8） 
   * - 0个正面（3阴）：老阴（6，变爻）
   */
  async generateCoinGua(question?: string): Promise<DivinationResponse> {
    const yaos: Yao[] = [];
    
    // 抛硬币6次，生成六爻
    for (let i = 0; i < 6; i++) {
      const coinResult = this.throwThreeCoins();
      yaos.push(coinResult);
    }

    // 获取卦象信息
    const guaXiang = this.getGuaXiangInfo(yaos);
    
    // 检查是否有变爻
    const changingYaos = yaos
      .map((yao, index) => (yao.isChanging ? index : -1))
      .filter(index => index !== -1);

    let bianGua: BianGua | undefined;
    if (changingYaos.length > 0) {
      bianGua = this.generateBianGua(yaos, changingYaos);
    }

    // 生成解读（传递用户问题）
    const interpretation = await this.generateInterpretation(guaXiang, bianGua, question);

    return {
      guaXiang,
      bianGua,
      interpretation
    };
  }

  /**
   * 抛三枚硬币，返回爻的结果
   */
  private throwThreeCoins(): Yao {
    // 模拟三枚硬币抛掷结果（0: 反面, 1: 正面）
    const coin1 = Math.random() > 0.5 ? 1 : 0;
    const coin2 = Math.random() > 0.5 ? 1 : 0;
    const coin3 = Math.random() > 0.5 ? 1 : 0;

    const yangCount = coin1 + coin2 + coin3; // 正面（阳面）数量
    
    switch (yangCount) {
      case 3: // 三个正面：老阳（9，变爻）
        return { value: 9, isChanging: true };
      case 2: // 两个正面：少阳（7）
        return { value: 7, isChanging: false };
      case 1: // 一个正面：少阴（8）
        return { value: 8, isChanging: false };
      case 0: // 零个正面：老阴（6，变爻）
        return { value: 6, isChanging: true };
      default:
        return { value: 7, isChanging: false }; // 默认少阳
    }
  }
}